﻿using Microsoft.AspNetCore.Http;
using Newtonsoft.Json.Linq;
using QBZ.Evaluation.Models;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Net.Http;
using System.Text;

namespace QBZ.Evaluation.Domains.OAuth
{
    public class QQ : LoginBase
    {
        public QQ(HttpContext contextAccessor,string redirect = null ) : base(contextAccessor)
        {
            if (redirect != null)
            {
                redirect_uri = redirect;
            }
            else
            {
                redirect_uri = contextAccessor.Request.Scheme + "://" + contextAccessor.Request.Host.Value + contextAccessor.Request.Path.Value;
            }
        }

        static readonly string authorize_url = "https://graph.qq.com/oauth2.0/authorize?response_type=code&client_id=" + LoginProvider.qq_client_id + "&redirect_uri=";
        static readonly string oauth_url = "https://graph.qq.com/oauth2.0/token";
        static readonly string openid_url = "https://graph.qq.com/oauth2.0/me";
        static readonly string user_info_url = "https://graph.qq.com/user/get_user_info";
        static readonly string user_info_url_params = "format=json&oauth_consumer_key=" + LoginProvider.qq_client_id + "&openid={0}&access_token={1}";
        string redirect_uri = "";

        public ResponseModel Authorize()
        {
            var res = new ResponseModel(ErrReason.Ok);
            try
            {
                var code = AuthorizeCode;
                if (string.IsNullOrEmpty(code))
                {
                    Context.Response.Redirect(authorize_url + redirect_uri, true);
                    return null;
                }
                else
                {
                    var errorMsg = string.Empty;
                    var token = Accesstoken(code, ref errorMsg);
                    if (string.IsNullOrEmpty(errorMsg))
                    {
                        var access_token = token;
                        res.result = UserInfo(access_token, ref errorMsg);
                        if (!string.IsNullOrEmpty(errorMsg))
                        {
                            res.status = new ResponseStatusModel {
                                code = ErrReason.OAuthFailld,
                                msg = "OAuthGetInfoFaild " + errorMsg
                            };
                        }
                    }
                    else
                    {
                        res.status = new ResponseStatusModel {
                            code = ErrReason.OAuthFailld,
                            msg = "OAuthFailld " + errorMsg
                        };
                    }
                }
            }
            catch (Exception ex)
            {
                res.status = new ResponseStatusModel{
                    code = ErrReason.UnknownError,
                    msg = ex.Message
                };
            }
            return res;
        }

        private string Accesstoken(string code, ref string errMsg)
        {
            var data = new SortedDictionary<string, string>();
            data.Add("client_id", LoginProvider.qq_client_id);
            data.Add("client_secret", LoginProvider.qq_client_secret);
            data.Add("grant_type", "authorization_code");
            data.Add("code", code);
            data.Add("redirect_uri", redirect_uri);
            var Params = string.Join("&", data.Select(x => x.Key + "=" + x.Value).ToArray());
            using (var wb = new HttpClient())
            {
                try
                {
                    var response = wb.PostAsync(oauth_url, new StringContent(Params)).Result;
                    var result = response.Content.ReadAsStringAsync().Result;
                    var kvs = result.Split(new string[] { "&" }, StringSplitOptions.RemoveEmptyEntries);
                    foreach (var v in kvs)
                    {
                        var kv = v.Split(new string[] { "=" }, StringSplitOptions.RemoveEmptyEntries);
                        if (kv[0] == "access_token") return kv[1];
                    }
                    errMsg = "access token not found";
                }
                catch (Exception ex)
                {
                    errMsg = ex.Message;
                }
            }
            return null;
        }

        private OAuthModel UserInfo(string token, ref string errMsg)
        {
            try
            {
                //获取openid
                var result = string.Empty;
                using (var wc = new HttpClient())
                {
                    var response = wc.PostAsync(openid_url, new StringContent("access_token=" + token)).Result;
                    result = response.Content.ReadAsStringAsync().Result;
                }
                result = result.Replace("callback(", string.Empty).Replace(");", string.Empty).Trim();
                var openid = Deserialize(result).Value<string>("openid");

                //通过openid取用户信息
                using (var wc = new HttpClient())
                {
                    var response = wc.PostAsync(user_info_url, new StringContent(string.Format(user_info_url_params, openid, token))).Result;
                    result = response.Content.ReadAsStringAsync().Result;
                }

                //返回相应的模型
                var user = Deserialize(result);
                var res = new OAuthModel
                {
                    BirthDay = user.Value<string>("year"),
                    City = user.Value<string>("city"),
                    FigureUrl = user.Value<string>("figureurl_qq_2"),
                    NickName = user.Value<string>("nickname"),
                    Province = user.Value<string>("province"),
                    Sex = user.Value<string>("gender"),
                    Token = token,
                    OAuthWay = OAuthWay.QQ,
                    OpenId = openid,
                };
                return res;
            }
            catch (Exception ex)
            {
                errMsg = ex.Message;
                return new OAuthModel{ Token = token };
            }
        }

    }
}
